#include "client.h"

void *client_thread(void *argv) {
    Client::CLIENTPARAM *param = (Client::CLIENTPARAM *)argv;
    int32_t i, ret;
    vector< uint8_t > cache;
    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    uint8_t buf[*param->cacheMax];
    cache.reserve(*param->cacheMax);
    getpeername(*param->fd, (struct sockaddr *)&addr, &len);
    // 循环获取服务器数据
    while (*param->signal) {
        // 重置数据
        ret = -1;
        cache.clear();
        memset(buf, 0, sizeof(buf));
        // 读取数据
        if (ret = (read(*param->fd, buf, sizeof(buf))) <= 0) {
            printf("failed to obtain server data! ret:%d\n", ret);
            continue;
        }
        // 保存数据
        for (i = 0; i < *param->cacheMax; i++)
            cache.push_back(buf[i]);
        if (param->caches->size() == *param->cacheMax)
            param->caches->pop_back();
        param->caches->insert(param->caches->begin(), cache);
    }
    pthread_exit(param->tid);
    return NULL;
}

Client::Client(const string address, const uint16_t port, const uint32_t cacheMax) {
    int32_t ret = -1;
    struct sockaddr_in addr = {0};
    // 初始化数据
    this->fd = -1, this->tid = -1, this->signal = 0, this->cacheMax = 0;
    vector< uint8_t >().swap(this->cache);
    vector< vector< uint8_t > >().swap(this->caches);
    memset(&this->param, 0, sizeof(this->param));
    // 保存缓存最值
    this->cacheMax = cacheMax;
    // 创建通信端口
    if ((this->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        throw runtime_error("failed to create communication port!\n");
    // 配置服务器信息
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = inet_addr(address.c_str());
    // 连接服务器
    if ((ret = connect(this->fd, (struct sockaddr *)&addr, sizeof(addr))) == -1) {
        close(this->fd);
        throw runtime_error("connection to server failed!\n");
    }
    // 创建线程
    this->signal = 1;
    this->param.fd = &this->fd;
    this->param.tid = &this->tid;
    this->param.signal = &this->signal;
    this->param.cacheMax = &this->cacheMax;
    this->param.caches = &this->caches;
    if (pthread_create(&this->tid, NULL, client_thread, &this->param)) {
        close(this->fd);
        throw runtime_error("client pthread_create error!\n");
    }
}

Client::~Client() {
    // 关闭线程
    if (this->signal != 0)
        this->signal = 0;
    // 关闭文件
    if (this->fd != -1)
        close(this->fd);
}

vector< uint8_t > &Client::read_data() {
    // 有数据
    if (this->caches.size()) {
        // 获取尾元素
        this->cache = this->caches.back();
        // 删除尾元素
        this->caches.pop_back();
        return this->cache;
    }
    // 无数据
    vector< uint8_t >().swap(this->cache);
    return this->cache;
}

Client &Client::write_data(const vector< uint8_t > data) {
    size_t i, size = data.size();
    uint8_t buf[this->cacheMax] = {0};
    // 拷贝数据
    for (i = 0; i < size && i < this->cacheMax; i++)
        buf[i] = data[i];
    // 发送数据
    write(this->fd, buf, sizeof(buf));
    return *this;
}